﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Reflection;
using System.Collections.Concurrent;

[assembly: InternalsVisibleTo("LaoLuo.Threading")]
namespace LaoLuo
{
    public static class PropertyContainer
    {
        private static ConcurrentDictionary<Type, IEnumerable<PropertyInfo>> _cache = new ConcurrentDictionary<Type, IEnumerable<PropertyInfo>>();

        /// <summary>
        /// Gets instance public properties, index-property (with name of 'Item') not included
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static IEnumerable<PropertyInfo> GetPropertiesInstancePublic(Type type)
        {
            return _cache.GetOrAdd(type, (k) => {
                return type.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(i => !i.Name.EqualsOrdinal("Item"));
            });
        }

        public static IEnumerable<PropertyInfo> GetPropertiesInstancePublic<T>()
        {
            return GetPropertiesInstancePublic(typeof(T));
        }

        public static PropertyInfo GetPropertyInstancePublic(Type type, string name, bool ignoreCase = true)
        {
            return GetPropertiesInstancePublic(type).SingleOrDefault(i => i.Name.EqualsOrdinal(name, ignoreCase));
        }

        public static PropertyInfo GetPropertyInstancePublic<T>(string name, bool ignoreCase = true)
        {
            return GetPropertyInstancePublic(typeof(T), name, ignoreCase);
        }
    }

    ///// <summary>
    ///// Provides static properties to get cached properties of specified type
    ///// </summary>
    ///// <typeparam name="T"></typeparam>
    //[Obsolete]
    //internal static class PropertyContainer<T>
    //{
    //    private static readonly IEnumerable<PropertyInfo> _propertiesInstancePublic;

    //    static PropertyContainer()
    //    {
    //        if (typeof(T) == typeof(object))
    //        {
    //            throw new TypeArgumentException("must be more specific then object");
    //        }

    //        _propertiesInstancePublic = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(i=>!i.Name.EqualsOrdinal("Item"));
    //    }

    //    /// <summary>
    //    /// Gets instance public properties, index-property (with name of 'Item') not included
    //    /// </summary>
    //    public static IEnumerable<PropertyInfo> PropertiesInstancePublic
    //    {
    //        get { return _propertiesInstancePublic; }
    //    }

    //    public static PropertyInfo GetPropertyInstancePublic(string name, bool ignoreCase = true)
    //    {
    //        return PropertiesInstancePublic.SingleOrDefault(i => i.Name.EqualsOrdinal(name, ignoreCase));
    //    }
    //}
}
